package ru.ifmo.rybakov.muclumon.pes;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.ifmo.rybakov.muclumon.Database;
import ru.ifmo.rybakov.muclumon.Properties;
import ru.ifmo.rybakov.muclumon.PropertyValueFactory;
import ru.ifmo.rybakov.muclumon.Task;
import ru.ifmo.rybakov.muclumon.TaskObserver;
import ru.ifmo.rybakov.muclumon.pes.sr.SequenceRunType;
import ru.ifmo.rybakov.muclumon.pes.sri.SequenceRunInfo;
import ru.ifmo.rybakov.muclumon.pes.sri.StepResult;

/**
 * Appends date and time the task was finished
 * @author gleb.rybakov
 *
 */
public class StepFinishedEventHandler implements IEventHandler {

	private static final Logger logger = LoggerFactory.getLogger(StepFinishedEventHandler.class);
	
	@SuppressWarnings("unchecked")
	@Override
	public void handle(SequenceRunInfo sequenceRunInfo,
			SequenceRunType sequenceRun) {
		
		// look for the task
		EntityManager em = Database.getEntityManagerFactory().createEntityManager();
		try {
			Query query = em.createQuery("SELECT t FROM Task t WHERE t.foreignId = :id");
			query.setParameter("id", Integer.valueOf(sequenceRun.getId().intValue()));
			List<Task> tasks = query.getResultList();
			if (tasks == null || tasks.size() != 1) {
				logger.warn("No task found, skipping event");
				return;
			}
			Task task = tasks.get(0);
			
			EntityTransaction t = em.getTransaction();
			try {
				t.begin();
				
				List<SequenceRunInfo.Step> steps = sequenceRunInfo.getStep();
				if (steps == null || steps.size() == 0) {
					logger.error("No step information on task (id={})", sequenceRunInfo.getId());
					return;
				}
				
				SequenceRunInfo.Step.Cluster clusterInfo = steps.get(0).getCluster();
				StepResult result = steps.get(0).getResult();
				task.addPropertyValue(PropertyValueFactory.createStringValue(Properties.TASK_RESULT, result.toString()));
				
				if (clusterInfo != null) {
					if (clusterInfo.getName() != null) {
						task.addPropertyValue(PropertyValueFactory.createStringValue(Properties.TASK_CLUSTER_NAME, clusterInfo.getName()));
					}
					if (clusterInfo.getNodeCount() != null) {
						task.addPropertyValue(PropertyValueFactory.createNumericValue(Properties.TASK_NODE_COUNT, Double.valueOf(clusterInfo.getNodeCount())));
					}
					if (clusterInfo.getNodeCount() != null) {
						task.addPropertyValue(PropertyValueFactory.createNumericValue(Properties.TASK_CORE_COUNT, Double.valueOf(clusterInfo.getCoreCount())));
					}
				}
				
				// add finished time
				task.addPropertyValue(PropertyValueFactory.createDateTimeValue(Properties.TASK_FINISHED,
						new DateTime(sequenceRunInfo.getTime().getStamp().toGregorianCalendar())));
				t.commit();
			} finally {
				if (t.isActive()) t.rollback();
			}
		} finally {
			em.close();
		}
		
		logger.debug("Step finished, step information updated (date and time), waiting for sequence to be finished");
		TaskObserver.getInstance().notifyOnTaskStopped();
	}

}
